﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Reap.Common.Runtime;

namespace Reap.Common.Runtime.Dependency.Ninject {
	/// <summary>
	/// 查找特性 并注册到容器里
	/// </summary>
	public class DependencyAttributeRegistrator {
		private readonly ITypeFinder _finder; //反射接口
		private readonly IContainerManager _containerManager; //容器接口
		
		public DependencyAttributeRegistrator(ITypeFinder finder, IContainerManager containerManager) {
			this._finder = finder;
			this._containerManager = containerManager;
		}

		/// <summary>
		/// 根据特性查找所有服务
		/// </summary>
		/// <returns></returns>
		public virtual IEnumerable<AttributeInfo<Reap.Common.Runtime.Dependency.DependencyAttribute>> FindServices() {
			foreach (Type type in _finder.FindClassesOfType<object>()) {
				var attributes = type.GetCustomAttributes(typeof(Reap.Common.Runtime.Dependency.DependencyAttribute), false);

				foreach (Reap.Common.Runtime.Dependency.DependencyAttribute attribute in attributes) {
					yield return new AttributeInfo<Reap.Common.Runtime.Dependency.DependencyAttribute> { Attribute = attribute, DecoratedType = type };
				}
			}
		}

		/// <summary>
		/// 注册服务
		/// </summary>
		public virtual void RegisterServices() {
			this.RegisterServices(FindServices());
		}

		/// <summary>
		/// 注册服务
		/// </summary>
		/// <param name="services"></param>
		public virtual void RegisterServices(IEnumerable<AttributeInfo<Reap.Common.Runtime.Dependency.DependencyAttribute>> services) {
			services = services.OrderBy(it => it.Attribute.Order);
			foreach (var info in services) {
				Type serviceType = info.Attribute.ServiceType ?? info.DecoratedType;
				_containerManager.AddComponent(serviceType, info.DecoratedType, info.Attribute.Key, info.Attribute.LifeStyle);
			}
		}
		/// <summary>
		/// 带参数的注册服务
		/// </summary>
		/// <param name="services"></param>
		/// <param name="configurationKeys"></param>
		/// <returns></returns>
		public virtual IEnumerable<AttributeInfo<Reap.Common.Runtime.Dependency.DependencyAttribute>> FilterServices(
			IEnumerable<AttributeInfo<Reap.Common.Runtime.Dependency.DependencyAttribute>> services, params string[] configurationKeys) {
			return services.Where(s => s.Attribute.Configuration == null || configurationKeys.Contains(s.Attribute.Configuration));
		}
	}
}
